package com.home.communication;

import java.io.IOException;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.widget.ListView;
import android.widget.Toast;

import com.home.activities.ResourceActivity;
import com.home.communication.ConnectionHandlers.ListResourceCategoriesHandler;
import com.home.communication.ConnectionHandlers.ListResourceHandler;
import com.home.communication.ConnectionHandlers.ResourceDetailsHandler;
import com.home.communication.ConnectionHandlers.RestartResouceHandler;
import com.home.communication.ConnectionHandlers.StartResouceHandler;
import com.home.constants.Consts;
import com.home.rhclient.Encryptor;
import com.home.rhclient.MainController;
import com.home.rhtester.R;

public class RestfulConnector {

	private ListResourceHandler listResourcesHandler;
	private StartResouceHandler startHandler;
	private RestartResouceHandler restartHandler;
	private ListResourceCategoriesHandler listCategorieHandler;
	private ResourceDetailsHandler resourceDetailsHandler;
	private Encryptor encryptor;
	private Context applicationContext;

	public RestfulConnector(Encryptor encrypt) {

		encryptor = encrypt;
		listCategorieHandler=new ListResourceCategoriesHandler();
		listResourcesHandler=new ListResourceHandler();
		startHandler=new StartResouceHandler();
		restartHandler=new RestartResouceHandler();
		resourceDetailsHandler=new ResourceDetailsHandler();
		
		
	}

	public void requestListofResourceCategories(JSONObject message,
			ListView list) throws Exception {
		listCategorieHandler.setListView(list);
		RESTfulRequest request = new RESTfulRequest(message,
				listCategorieHandler, Consts.URL_LIST_CATEGORIES,list.getContext());
		request.send();
	}

	public void requestListofResoruces(JSONObject message, ListView listView)
			throws Exception {
		listResourcesHandler.setListView(listView);
		RESTfulRequest request = new RESTfulRequest(message,
				listResourcesHandler, Consts.URL_LIST_RESOURCE,listView.getContext());
		request.send();
	}

	public void startResource(JSONObject message, ResourceActivity activity)
			throws Exception {
		startHandler.setResourceActivity(activity);
		RESTfulRequest request = new RESTfulRequest(message, startHandler,
				Consts.URL_START_RESOURCE,activity);
		request.send();
	}
	
	
	public void restartResource(JSONObject message, ResourceActivity activity)
			throws Exception {
		restartHandler.setResourceActivity(activity);
		RESTfulRequest request = new RESTfulRequest(message, restartHandler,
				Consts.URL_START_RESOURCE,activity);
		request.send();
	}

	public void requestResourceDetail(JSONObject message,ResourceActivity activity) throws Exception {
		resourceDetailsHandler.setResourceActivity(activity);
		RESTfulRequest request = new RESTfulRequest(message,
				resourceDetailsHandler, Consts.URL_RESOURCE_DETAILS,activity);
		request.send();
	}

	private class RESTfulRequest implements Runnable {
		JSONObject msg;
		String signature;

		HttpPost httppost;
		HttpResponse response;
		HttpClient httpclient;
		HttpContext httpContext;
		Handler threadHandler;

		Bundle returnBundle;

		public RESTfulRequest(JSONObject jsonObj, Handler threadHandler,
				String url, Context context) throws Exception {
			msg = jsonObj;
			applicationContext = context;
			HttpParams myParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(myParams, 10000);// connection
																		// timeout
			HttpConnectionParams.setSoTimeout(myParams, 10000);// wait for data
																// timeout

			httpContext = new BasicHttpContext();
			httppost = new HttpPost(url);
			httpclient = new DefaultHttpClient(myParams);
			returnBundle = new Bundle();
			this.threadHandler = threadHandler;
		}

		public void send() {
			Thread thread = new Thread(this);
			thread.start();
		}

		@Override
		public void run() {

			try {
				signature = encryptor.rsaEncrypt(String.valueOf(msg.toString()
						.hashCode()));
				ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
				params.add(new BasicNameValuePair(Consts.PARAM_MESSAGE, msg
						.toString()));
				params.add(new BasicNameValuePair(Consts.PARAM_SIGNATURE,
						signature));
				UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params,
						HTTP.UTF_8);
				httppost.setEntity(ent);
				Log.v("RESTfulRequest", signature);
				// httpget.addHeader(Consts.PARAM_SIGNATURE,signature);

				// Log.v("Header",);
				response = httpclient.execute(httppost, httpContext);
				String msgReceived = EntityUtils.toString(response.getEntity());
				Message msg = new Message();
				// Send server response to the Thread Handler
				returnBundle.putString("response", msgReceived);
				msg.setData(returnBundle);
				msg.setTarget(threadHandler);
				msg.sendToTarget();
			} catch (ConnectTimeoutException e) {
				
				MainController.GetInstance().currentActivity.runOnUiThread(new Runnable() {
					
					@Override
					public void run() {
						Toast t=Toast.makeText(applicationContext, R.string.connection_timed_out, Toast.LENGTH_SHORT);
						t.setGravity(Gravity.CENTER, 0, 0);
						t.show();
						
					}
				});
				
			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}
}
